from bpy.types import Panel
from os.path import splitext
from ...addon.naming import FluidLabNaming
from ..ui_module_panel import FLUIDLAB_ModulePanel
from ...libs.functions.get_common_vars import get_common_vars
from ...libs.functions.common_ui_elements import title_header, collapsable
from ...libs.functions.nodes import node_prop_visualize_in_ui, color_ramp_ui, get_node_index_or_identifier_by


def ui_map_range(layout, node_tree, node_name:str) -> None:
    row = layout.row(align=True)
    node_prop_visualize_in_ui(row, node_tree, node_name, "inputs", "From Min", "From Min | Max")
    node_prop_visualize_in_ui(row, node_tree, node_name, "inputs", "From Max", "")
    row = layout.row(align=True)
    node_prop_visualize_in_ui(row, node_tree, node_name, "inputs", "To Min", "To Min | Max")
    node_prop_visualize_in_ui(row, node_tree, node_name, "inputs", "To Max", "")


def leyenda(layout, shader_props,  active_mesh=None):
    leyenda = layout.box().row(align=True)
    leyenda.alignment = 'CENTER'
    leyenda.scale_y = 0.5

    if active_mesh is not None:
        mat_name = active_mesh.active_material.name
    else:
        mat_name = str(splitext(shader_props.thumbnails)[0])

    text = "Custom" if shader_props.material_types == 'CUSTOM' else mat_name
    leyenda.label(text=text)
    #leyenda.label(text=f"{splitext(shader_props.thumbnails)[0]}")


def assing_material(main_col, col, shader_props):

    if not shader_props.enum_items:
        return

    main_col = col.box().column(align=True)

    # size_y = 8
    size_y = 10
    size_x = 1.18

    header = main_col.box().row(align=True)
    header.alignment = 'CENTER'
    header.scale_y = 1
    header.label(text=f"Materials")

    thumb_row = main_col.row(align=True)
    thumb_row.enabled = shader_props.material_types != 'CUSTOM'
    arrow_l = thumb_row.row(align=True)
    arrow_l.operator("fluidlab.shading_tmbs_arrows", text="", icon='TRIA_LEFT').direction = 'LEFT'
    arrow_l.scale_y = size_y
    arrow_l.scale_x = size_x

    thumb_row.template_icon_view(shader_props, "thumbnails", show_labels=True, scale=size_y, scale_popup=6)
    
    arrow_r = thumb_row.row(align=True)
    arrow_r.operator("fluidlab.shading_tmbs_arrows", text="", icon='TRIA_RIGHT').direction = 'RIGHT'
    arrow_r.scale_y = size_y
    arrow_r.scale_x = size_x

    leyenda(main_col, shader_props)

    selector_type = main_col.row(align=True)
    selector_type.use_property_split = False
    selector_type.scale_y = 1.3
    selector_type.prop(shader_props, "material_types", expand=True, text=" ")

    if shader_props.material_types == 'CUSTOM':
        main_col.separator(factor=0.8)
        main_col.prop(shader_props, "material_pointer")
    
    main_col.separator(factor=0.8)

    add_mat_bt = main_col.row(align=True)
    add_mat_bt.scale_y = 1.3
    add_mat_bt.operator("fluidlab.shading_add_material", text="Assing Material")

def mat_settings_material(context, main_col, col, active_mesh, toggles, shader_props):
    
    active_mat = active_mesh.active_material
    GN_mod = active_mesh.modifiers.get(FluidLabNaming.GN_MESH_MOD)
    
    if not active_mat or active_mat.name.startswith("FLuidLab_Basic_Shader_"):
        return
    
    main_col = col.box().column(align=True)
    
    leyenda(main_col, shader_props, active_mesh)
 
    if shader_props.material_types == 'CUSTOM':
        
        main_col.box().label(text="I cannot handle custom materials from here", icon='INFO')

    else:

        # Nuestros materiales UI:
        is_lava = active_mat.name.lower().startswith("lava")
        is_cycles_lava = active_mat.name.lower().startswith("cycleslava")
        is_blood = active_mat.name.lower().startswith("blood")
        is_water_light = active_mat.name.lower().startswith("waterlight")
        is_water = active_mat.name.lower().startswith("water")
        is_chocolat = active_mat.name.lower().startswith("chocolat")
        is_sand = active_mat.name.lower().startswith("sand")
        is_mercury = active_mat.name.lower().startswith("mercury")
        is_mixcolors = active_mat.name.lower().startswith("mixcolors")

        # Leer y exponer los inputs de x nodos de material para poder manipularlos desde nuestra ui:
        node_tree = active_mat.node_tree
        nodes = node_tree.nodes
        main_settings = next((node for node in nodes if node.name.startswith("main_settings")), None)

        if main_settings is None:
            main_col.box().label(text="Unassigned Material!", icon="INFO")
        
        if main_settings:

            main_col.separator()
            materials_ui = main_col.column()

            with_color_ramps = ("blood", "honey", "oil", "petroleum", "sand", "chocolat", "lava")
            with_cr = next((True for wc in with_color_ramps if active_mat.name.lower().startswith(wc)), False)
            if with_cr:

                # Color ramp:
                c_ramp = collapsable(
                    materials_ui,
                    toggles,
                    "color_ramp",
                    "Color Ramp",
                    'RESTRICT_COLOR_ON',
                    align=False,
                )
                if c_ramp:
                    col_ramp_path = (
                        active_mat,
                        "color_ramp"
                    )
                    color_ramp_ui(context, c_ramp, active_mat, col_ramp_path)

                # pointiness_ramp:
                if is_blood:
                    p_c_ramp = collapsable(
                        materials_ui,
                        toggles,
                        "pointiness_ramp",
                        "Pointiness Ramp",
                        'RESTRICT_COLOR_ON',
                        align=False,
                    )
                    if p_c_ramp:

                        pointiness_path = (
                            active_mat,
                            "pointiness_ramp"
                        )
                        color_ramp_ui(context, p_c_ramp, active_mat, pointiness_path)

            else:
                if not is_mixcolors and not is_cycles_lava:
                    # Principled single color:
                    node_prop_visualize_in_ui(materials_ui, node_tree, "main_settings", "inputs", "Base Color", "Color")

            # Sand Hue saturation 
            if is_sand:
                materials_ui = col.box().column(align=True)
                node_prop_visualize_in_ui(materials_ui, node_tree, "SandHueSaturationValue", "inputs", "Hue", "Hue")
                node_prop_visualize_in_ui(materials_ui, node_tree, "SandHueSaturationValue", "inputs", "Saturation", "Saturation") 
                node_prop_visualize_in_ui(materials_ui, node_tree, "SandHueSaturationValue", "inputs", "Value", "Value")
                node_prop_visualize_in_ui(materials_ui, node_tree, "SandHueSaturationValue", "inputs", "Fac", "Factor") 

            # Si es Water Light muestro el Emission Color:
            if is_water_light:

                node_prop_visualize_in_ui(materials_ui, node_tree, "ColorStrength", "inputs", "Color", "Emission Color")
                node_prop_visualize_in_ui(materials_ui, node_tree, "ColorStrength", "inputs", "Strength", "Strength")
                
                wl_mask = collapsable(
                        materials_ui,
                        toggles,
                        "water_light_mask_map_range",
                        "Light Mask MapRange",
                        'RESTRICT_COLOR_ON',
                        align=False,
                    )
                if wl_mask:
                    ui_map_range(wl_mask, node_tree, "MapRange")

            if not is_sand:
                materials_ui = col.box().column(align=True)

            if is_lava:
                                    
                # Lava:
                mask_vel_map_range = collapsable(
                        materials_ui,
                        toggles,
                        "mask_vel_map_range",
                        "Mix Velocity/Lifetime",
                        'RESTRICT_COLOR_ON',
                        align=True,
                    )
                if mask_vel_map_range:
                    node_prop_visualize_in_ui(mask_vel_map_range, node_tree, "Mix_Lavattrs", "inputs", "Mix Attribute", "Mix Attribute")
                    node_prop_visualize_in_ui(mask_vel_map_range, node_tree, "Mix_Lavattrs", "inputs", "Max Velocity", "Max Velocity")
                    node_prop_visualize_in_ui(mask_vel_map_range, node_tree, "Mix_Lavattrs", "inputs", "Max Lifetime", "Max Lifetime")

                # Para controlar el Roughness de la pieda o de la lava tenemos el color ramp RoughComp:
                rcomp = collapsable(
                        materials_ui,
                        toggles,
                        "roughcomp",
                        "Roughness",
                        'RESTRICT_COLOR_ON',
                        align=True,
                    )
                if rcomp:
                    color_ramp_ui(context, rcomp, active_mat, (active_mat, "RoughComp"))
                
                # Color Ramp Pointiness cracks effect :
                crpointiness = collapsable(
                        materials_ui,
                        toggles,
                        "cramp_pointiness",
                        "Pointiness",
                        'RESTRICT_COLOR_ON',
                        align=True,
                    )
                if crpointiness:
                    
                    if shader_props.vec_color_shading == 'SHADING':
                        pointiness_mask_or_color = crpointiness.row(align=True)
                        pointiness_mask_or_color.scale_y = 1.3
                        pointiness_mask_or_color.prop(shader_props, "pointiness_mask_or_color", toggle=True, text="Preview Mask", expand=True)
                        crpointiness.separator()

                    color_ramp_ui(context, crpointiness, active_mat, (active_mat, "PointinessColorRamp"))
                    crpointiness.separator()
                    node_prop_visualize_in_ui(crpointiness, node_tree, "PointinessAmount", "inputs", "Factor", "Pointiness Factor")

                materials_ui = col.box().column(align=True)

            vec_color_shading = materials_ui.row(align=True)
            vec_color_shading.scale_y = 1.3

            # Excepcion para la cycles lava: 
            vc_prop = "cycles_lava_shading_or_mask" if is_cycles_lava else "vec_color_shading" 
            vec_color_shading.prop(shader_props, vc_prop, toggle=True, text="Display as", expand=True)

            if vc_prop == "vec_color_shading":
                if shader_props.vec_color_shading == 'VELOCITY':
                    vel_map_range = materials_ui.row(align=True)
                    node_prop_visualize_in_ui(vel_map_range, node_tree, "Velocity_Map_Range", "inputs", "From Max", "Max Velocity")

            
            #--------------------------------------------------------------------------------------------------------------------
            # Cycles Lava
            #--------------------------------------------------------------------------------------------------------------------
            if is_cycles_lava:

                cl_uv_vector_switch = collapsable(
                        col,
                        toggles,
                        "cl_uv_vector_switch",
                        "UV Coordinates",
                        'MOD_UVPROJECT',
                        align=True,
                    )
                if cl_uv_vector_switch:
                    # node_prop_visualize_in_ui(cl_uv_vector_switch, node_tree, "UV_Vector_Switch", "inputs", "Factor", "Factor")
                    uv_vect = cl_uv_vector_switch.row(align=True)
                    uv_vect.scale_y = 1.3
                    uv_vect.prop(shader_props, "uv_vector_switch", toggle=True, text="Coordinates", expand=True)
                    # UV_Vector_Mapping
                    node_prop_visualize_in_ui(cl_uv_vector_switch, node_tree, "UV_Vector_Mapping", "inputs", "Scale", "Scale")

                cl_lifetime_or_velocity = collapsable(
                        col,
                        toggles,
                        "cl_lifetime_or_velocity",
                        "Lifetime or Velocity",
                        'AREA_SWAP',
                        align=True,
                    )
                if cl_lifetime_or_velocity:
                    node_prop_visualize_in_ui(cl_lifetime_or_velocity, node_tree, "CL_Lifetime_or_Velocity", "inputs", "Value", "Value")
                
                cl_ctrls = collapsable(
                        col,
                        toggles,
                        "cl_ctrls",
                        "Magma and BlackRock",
                        'BRUSH_SOFTEN',
                        align=True,
                    )
                if cl_ctrls:
                    node_prop_visualize_in_ui(cl_ctrls, node_tree, "CL_LavaCtrls", "inputs", "Magma Expand", "Magma Expand")
                    node_prop_visualize_in_ui(cl_ctrls, node_tree, "CL_LavaCtrls", "inputs", "Magma Intensity", "Magma Intensity")
                    node_prop_visualize_in_ui(cl_ctrls, node_tree, "CL_LavaCtrls", "inputs", "BlackRock Intensity Expand", "BlackRock Expand")
                    node_prop_visualize_in_ui(cl_ctrls, node_tree, "CL_LavaCtrls", "inputs", "BlackRock Intensity", "BlackRock Intensity")
                
                cl_lifetime = collapsable(
                        col,
                        toggles,
                        "cl_lifetime",
                        "Lifetime Map Range",
                        'COLORSET_13_VEC',
                        align=True,
                    )
                if cl_lifetime:
                    ui_map_range(cl_lifetime, node_tree, "Lifetime_Map_Range")
                    
                cl_velocity = collapsable(
                        col,
                        toggles,
                        "cl_velocity",
                        "Velocity Map Range",
                        'COLORSET_13_VEC',
                        align=True,
                    )
                if cl_velocity:
                    ui_map_range(cl_velocity, node_tree, "Velocity_Map_Range")

                cl_main = collapsable(
                        col,
                        toggles,
                        "cl_main",
                        "Main",
                        'MATERIAL',
                        align=True,
                    )
                if cl_main:
                    node_prop_visualize_in_ui(cl_main, node_tree, "main_settings", "inputs", "Base Color", "Color")
                    node_prop_visualize_in_ui(cl_main, node_tree, "main_settings", "inputs", "Roughness", "Roughness") 

                    # Temperature Color:
                    cl_main = col.box().column(align=True)
                    cl_main.label(text="Temperature Color")

                    blackbody_switcher = cl_main.row(align=True)
                    blackbody_switcher.scale_y = 1.3
                    blackbody_switcher.prop(shader_props, "blackbody_switcher", toggle=True, text="Mode", expand=True)
                    node_prop_visualize_in_ui(cl_main, node_tree, "CL_Blackbody_Value", "outputs", "Value", "Temperature", index=0)
                    node_prop_visualize_in_ui(cl_main, node_tree, "CL_Blackbody_Multiply", "inputs", "Value_001", "Multiply", index=1)

                    cl_main = col.box().column(align=True)
                    cl_main.label(text="Displace")

                    # Displace:
                    node_prop_visualize_in_ui(cl_main, node_tree, "CL_Displacement", "inputs", "Scale", "Scale")

                    cl_main = col.box().column(align=True)
                    cl_main.label(text="Noise")

                    # Noise:
                    node_prop_visualize_in_ui(cl_main, node_tree, "CL_noise", "inputs", "Scale", "Scale")
                    node_prop_visualize_in_ui(cl_main, node_tree, "CL_noise", "inputs", "Detail", "Detail")
                    node_prop_visualize_in_ui(cl_main, node_tree, "CL_noise", "inputs", "Roughness", "Roughness")
                    node_prop_visualize_in_ui(cl_main, node_tree, "CL_noise", "inputs", "Lacunarity", "Lacunarity")
                    node_prop_visualize_in_ui(cl_main, node_tree, "CL_noise", "inputs", "Distortion", "Distortion")


            #--------------------------------------------------------------------------------------------------------------------
            # Lava
            #--------------------------------------------------------------------------------------------------------------------
            if is_lava:
                # node_prop_visualize_in_ui(materials_ui, node_tree, "BurntMix", "inputs", "Factor", "Burnt Mix")                        
                node_prop_visualize_in_ui(materials_ui, node_tree, "EmissionPower", "inputs", "Value", "Emission Power", 1)                                
                node_prop_visualize_in_ui(materials_ui, node_tree, "CracksScale", "outputs", "Value", "Cracks Scale")

                # "LavaColorMapRange"
                materials_ui.separator()
                materials_ui = col.box().column(align=True)

                ui_map_range(materials_ui, node_tree, "LavaColorMapRange")
                
                # materials_ui.separator()
                materials_ui = col.box().column(align=True)


            if not is_lava and not is_mixcolors and not is_cycles_lava:
                materials_ui = col.box().column(align=True)

                # Roughness:
                node_prop_visualize_in_ui(materials_ui, node_tree, "main_settings", "inputs", "Roughness", "Roughness") 

                # IOR:
                node_prop_visualize_in_ui(materials_ui, node_tree, "main_settings", "inputs", "IOR", "IOR") 

                # Transmission Weight:
                node_prop_visualize_in_ui(materials_ui, node_tree, "main_settings", "inputs", "Transmission Weight", "Transmission Weight") 


            # SSS:
            main_settings_with_sss = ("water", "blood", "chocolat", "honey", "milk", "oil", "petroleum")
            with_sss = next((True for w_sss in main_settings_with_sss if active_mat.name.lower().startswith(w_sss)), False)
            if with_sss:
                materials_ui.separator()
                node_prop_visualize_in_ui(materials_ui, node_tree, "main_settings", "inputs", "Subsurface Weight", "Subsurface Weight")
                node_prop_visualize_in_ui(materials_ui, node_tree, "main_settings", "inputs", "Subsurface Scale", "Subsurface Scale")

                materials_ui = col.box().column(align=True)


            # Switch
            if not is_lava and not is_sand and not is_mixcolors and not is_cycles_lava:
                show_volume = materials_ui.row(align=True)
                show_volume.scale_y = 1.3
                show_volume.prop(shader_props, "show_volume", toggle=True, text="Show internal volume")
                # node_prop_visualize_in_ui(materials_ui, node_tree, "switch", "inputs", "Fac", "Switch")
                
            # rgb volume:
            node_prop_visualize_in_ui(materials_ui, node_tree, "rgb_volume", "outputs", "Color", "Volume Color")

            # Density absortion:
            node_prop_visualize_in_ui(materials_ui, node_tree, "vol_absorption", "inputs", "Density", "Density Absorption")
            node_prop_visualize_in_ui(materials_ui, node_tree, "vol_scatter", "inputs", "Density", "Density Scatter")
            node_prop_visualize_in_ui(materials_ui, node_tree, "vol_scatter", "inputs", "Anisotropy", "Anisotropy")

            # Bump:
            if not is_chocolat:
                
                if not is_lava and not is_mercury and not is_cycles_lava:
                    materials_ui = col.box().column(align=True)

                node_prop_visualize_in_ui(materials_ui, node_tree, "Bump", "inputs", "Strength", "Bump Strength")

                # text_noise
                node_prop_visualize_in_ui(materials_ui, node_tree, "text_noise", "inputs", "Scale", "Noise Scale")
                node_prop_visualize_in_ui(materials_ui, node_tree, "text_noise", "inputs", "Detail", "Noise Detail")
                node_prop_visualize_in_ui(materials_ui, node_tree, "text_noise", "inputs", "Distortion", "Noise Distortion")
        
            # MixColors:
            if is_mixcolors and GN_mod:
                
                # Mostramos el Blur del FluidLab_Mesh_Mod -> FluidLab_Mesh_GN -> nodo BlurNode:
                node_prop_visualize_in_ui(materials_ui, GN_mod.node_group, FluidLabNaming.ITERATIONS_BLUR_NODE, "inputs", "Iterations", "Blur")

                index_switch_node_name = FluidLabNaming.INDEX_SW_COLORS
                index_switch_node = GN_mod.node_group.nodes.get(index_switch_node_name)
                if index_switch_node:

                    id_count = len(index_switch_node.inputs[1:-1]) # <- cribando el '' (vacio) y el "Index"
                    for int_id in range(id_count):
                        str_id = str(int_id)
                        node_prop_visualize_in_ui(materials_ui, GN_mod.node_group, FluidLabNaming.INDEX_SW_COLORS, "inputs", str_id, f"Color {str_id}")

                materials_ui.separator()
                principled_porps = {
                                    "principled_main_porps": [
                                                                    "Metallic", 
                                                                    "Roughness", 
                                                                    "IOR", 
                                                                    "Alpha",
                                    ],
                                    "principled_subsurface_porps": [
                                                                    "Subsurface Weight", 
                                                                    "Subsurface Raius", 
                                                                    "Subsurface Scale",
                                                                    "Subsurface Anisotropy",
                                    ],
                                    "principled_specular_porps": [
                                                                    "Specular IOR Level",
                                                                    "Specular Tint",
                                                                    "Anisotropic",
                                                                    "Anisotropic Rotation",
                                                                    "Tangent", 
                                    ],
                                    "principled_transmission_porps": [
                                                                    "Transmission Weight",
                                    ],
                                    "principled_coat_porps": [
                                                                    "Coat Weight",
                                                                    "Coat Roughness",
                                                                    "Coat IOR",
                                                                    "Coat Tint",
                                                                    "Coat Normal",
                                    ],
                                    "principled_sheen_porps": [
                                                                    "Sheen Weight",
                                                                    "Sheen Roughness",
                                                                    "Sheen Tint",
                                    ],
                                    "principled_emission_porps": [
                                                                    "Emission Color",
                                                                    "Emission Strength",
                                    ]
                }
                props_with_prev_post_space = ["Subsurface Raius", "Coat Normal", "Tangent"]
                for prop_collaps, props_names in principled_porps.items():
                    
                    label_out = prop_collaps.replace("principled_", "").replace("_porps", "").title()
                    if label_out == "Main":
                        label_out = "Principled"

                    collaps = collapsable(
                        materials_ui,
                        active_mat.fluidlab,
                        prop_collaps,
                        label_out,
                        'NONE',
                        align=True,
                    )
                    if collaps:
                        for prop_name in props_names:
                            
                            arguments = {
                                            "layout": collaps, 
                                            "node_tree": node_tree, 
                                            "target_node_name": "main_settings", 
                                            "target_io_type": "inputs", 
                                            "prop_name": prop_name, 
                                            "ui_name": prop_name,
                                            "index": 7 if prop_name == "Subsurface Raius" else None
                                        }
                            
                            if prop_name in props_with_prev_post_space:
                                collaps.separator()
                            
                            # Pintamos las propiedades:
                            node_prop_visualize_in_ui(**arguments)
                            
                            if prop_name in props_with_prev_post_space:
                                collaps.separator()



class FLUIDLAB_PT_shading_ui(Panel, FLUIDLAB_ModulePanel):
    fluidlab_section = 'SHADING'
    bl_idname = "FLUIDLAB_PT_shading_ui"
    bl_label = "Module"

    def draw(self, context):

        fluid_mesh, ui, toggles, shader_props = get_common_vars(context, get_fluid_mesh=True, get_ui=True, get_toggles=True, get_shader_props=True)

        layout = self.layout
        layout.use_property_split = True
        layout.use_property_decorate = False

        col = layout.column(align=True)
        title_header(col, "Shading")

        main_col = col.box().column(align=True)
        main_col.use_property_split = True
        main_col.use_property_decorate = False

        if ui.ui_mode == 'BASIC':
        
            # ------------- #
            """ UI BASICA """
            # ------------- #
        
            main_col.label(text="Hola Mundo Basico")

    
        elif ui.ui_mode == 'ADVANCED':
        
            # --------------- #
            """ UI AVANZADA """
            # --------------- # 
            

            # NOTA: Si se usa arena (particles), igualmente se usará el mesh generado, las particles por geometry o instance, se crean con ese GN.            

            if fluid_mesh.is_void:

                main_col.box().label(text=FluidLabNaming.NO_MESHES_AVAIL, icon='INFO')

            else:
                    
                main_col.template_list("FLUIDLAB_UL_draw_fluids_mesh", "", fluid_mesh, "list", fluid_mesh, "list_index", rows=3)

                active_mesh_item = fluid_mesh.active
                active_mesh = active_mesh_item.ob
    
                subsections = main_col.row(align=True)
                subsections.scale_y = 1.3
                subsections.use_property_split = False
                subsections.prop(shader_props, "shader_subsectioins", expand=True, text=" ")
                # main_col.separator()

                if shader_props.shader_subsectioins == 'ASSING':
                    assing_material(main_col, col, shader_props)

                elif shader_props.shader_subsectioins == 'MAT_SETTINGS': 
                    mat_settings_material(context, main_col, col, active_mesh, toggles, shader_props)